<template>
  <div class="canvas-container">
    <el-container style="height: 100%;">
      <el-header style="height: auto;z-index: 999;">
        <div class="menu" editor-component="menu">
          <div class="menu-item">
            <div class="menu-item__undo">
              <i></i>
            </div>
            <div class="menu-item__redo">
              <i></i>
            </div>
            <div class="menu-item__painter" title="格式刷(双击可连续使用)">
              <i></i>
            </div>
            <div class="menu-item__format" title="清除格式">
              <i></i>
            </div>
          </div>
          <div class="menu-divider"></div>
          <div class="menu-item">
            <div class="menu-item__font">
              <span class="select" title="字体">微软雅黑</span>
              <div class="options">
                <ul>
                  <li v-for="item in fontFamilyList" :key="item.value" :data-family="item.value"
                    :style="{ fontFamily: item.value }">{{ item.label }}</li>
                </ul>
              </div>
            </div>
            <div class="menu-item__size">
              <span class="select" title="字体">小四</span>
              <div class="options">
                <ul>
                  <li v-for="size in fontSizeList" :key="size.value" :data-size="size.value">{{ size.label }}</li>
                </ul>
              </div>
            </div>
            <div class="menu-item__size-add">
              <i></i>
            </div>
            <div class="menu-item__size-minus">
              <i></i>
            </div>
            <div class="menu-item__bold">
              <i></i>
            </div>
            <div class="menu-item__italic">
              <i></i>
            </div>
            <div class="menu-item__underline">
              <i></i>
            </div>
            <div class="menu-item__strikeout" title="删除线">
              <i></i>
            </div>
            <div class="menu-item__superscript">
              <i></i>
            </div>
            <div class="menu-item__subscript">
              <i></i>
            </div>
            <div class="menu-item__color" title="字体颜色">
              <i></i>
              <span></span>
              <input type="color" id="color" />
            </div>
            <div class="menu-item__highlight" title="高亮">
              <i></i>
              <span></span>
              <input type="color" id="highlight">
            </div>
          </div>
          <div class="menu-divider"></div>
          <div class="menu-item">
            <div class="menu-item__title">
              <i></i>
              <span class="select" title="切换标题">正文</span>
              <div class="options">
                <ul>
                  <li style="font-size:16px;">正文</li>
                  <li v-for="title in titleList" :key="title.value" :data-level="title.value"
                    :style="{ fontSize: title.size + 'px' }">{{ title.label }}</li>
                </ul>
              </div>
            </div>
            <div class="menu-item__left">
              <i></i>
            </div>
            <div class="menu-item__center">
              <i></i>
            </div>
            <div class="menu-item__right">
              <i></i>
            </div>
            <div class="menu-item__alignment">
              <i></i>
            </div>
            <div class="menu-item__row-margin">
              <i title="行间距"></i>
              <div class="options">
                <ul>
                  <li v-for="space in spaceList" :key="space.value" :data-rowmargin="space.value">{{ space.label }}</li>
                </ul>
              </div>
            </div>
            <div class="menu-item__list">
              <i></i>
              <div class="options">
                <ul>
                  <li>
                    <label>取消列表</label>
                  </li>
                  <li data-list-type="ol" data-list-style='decimal'>
                    <label>有序列表：</label>
                    <ol>
                      <li>________</li>
                    </ol>
                  </li>
                  <li data-list-type="ul" data-list-style='disc'>
                    <label>实心圆点列表：</label>
                    <ul style="list-style-type: disc;">
                      <li>________</li>
                    </ul>
                  </li>
                  <li data-list-type="ul" data-list-style='circle'>
                    <label>空心圆点列表：</label>
                    <ul style="list-style-type: circle;">
                      <li>________</li>
                    </ul>
                  </li>
                  <li data-list-type="ul" data-list-style='square'>
                    <label>空心方块列表：</label>
                    <ul style="list-style-type: square;">
                      <li>________</li>
                    </ul>
                  </li>
                </ul>
              </div>
            </div>
          </div>
          <div class="menu-divider"></div>
          <div class="menu-item">
            <div class="menu-item__table">
              <i title="表格"></i>
            </div>
            <div class="menu-item__table__collapse">
              <div class="table-close">×</div>
              <div class="table-title">
                <span class="table-select">插入</span>
                <span>表格</span>
              </div>
              <div class="table-panel"></div>
            </div>
            <!-- <div class="menu-item__image">
            <i title="图片"></i>
            <input type="file" id="image" accept=".png, .jpg, .jpeg, .svg, .gif">
          </div> -->
            <div class="menu-item__hyperlink">
              <i title="超链接"></i>
            </div>
            <div class="menu-item__separator">
              <i title="分割线"></i>
              <div class="options">
                <ul>
                  <li data-separator='0,0'>
                    <i></i>
                  </li>
                  <li data-separator="1,1">
                    <i></i>
                  </li>
                  <li data-separator="3,1">
                    <i></i>
                  </li>
                  <li data-separator="4,4">
                    <i></i>
                  </li>
                  <li data-separator="7,3,3,3">
                    <i></i>
                  </li>
                  <li data-separator="6,2,2,2,2,2">
                    <i></i>
                  </li>
                </ul>
              </div>
            </div>
            <!-- <div class="menu-item__watermark">
            <i title="水印(添加、删除)"></i>
            <div class="options">
              <ul>
                <li data-menu="add">添加水印</li>
                <li data-menu="delete">删除水印</li>
              </ul>
            </div>
          </div>
          <div class="menu-item__codeblock" title="代码块">
            <i></i>
          </div>
          <div class="menu-item__page-break" title="分页符">
            <i></i>
          </div>
          <div class="menu-item__control">
            <i title="控件"></i>
            <div class="options">
              <ul>
                <li data-control='text'>文本</li>
                <li data-control="select">列举</li>
                <li data-control="checkbox">复选框</li>
              </ul>
            </div>
          </div>
          <div class="menu-item__checkbox" title="复选框">
            <i></i>
          </div>
          <div class="menu-item__latex" title="LateX">
            <i></i>
          </div>
          <div class="menu-item__date">
            <i title="日期"></i>
            <div class="options">
              <ul>
                <li data-format="yyyy-MM-dd"></li>
                <li data-format="yyyy-MM-dd hh:mm:ss"></li>
              </ul>
            </div>
          </div>
          <div class="menu-item__block" title="内容块">
            <i></i>
          </div> -->
          </div>
          <div class="menu-divider"></div>
          <div class="menu-item">
            <div class="menu-item__search" data-menu="search">
              <i></i>
            </div>
            <div class="menu-item__search__collapse" data-menu="search">
              <div class="menu-item__search__collapse__search">
                <input type="text" />
                <label class="search-result"></label>
                <div class="arrow-left">
                  <i></i>
                </div>
                <div class="arrow-right">
                  <i></i>
                </div>
                <span>×</span>
              </div>
              <div class="menu-item__search__collapse__replace">
                <input type="text">
                <button>替换</button>
              </div>
            </div>
            <div class="menu-item__print" data-menu="print">
              <i></i>
            </div>
          </div>
        </div>
      </el-header>
      <el-main class="content">
        <div id="canvasEditor" class="canvas-editor" editor-component="main"></div>
      </el-main>
      <el-footer style="height: 30px;">
        <div class="footer" editor-component="footer">
          <div>
            <div class="page-mode">
              <i title="页面模式(分页、连页)"></i>
              <div class="options">
                <ul>
                  <li data-page-mode="paging" class="active">分页</li>
                  <li data-page-mode="continuity">连页</li>
                </ul>
              </div>
            </div>
            <span>可见页码：<span class="page-no-list">1</span></span>
            <span>页面：<span class="page-no">1</span>/<span class="page-size">1</span></span>
            <span>字数：<span class="word-count">0</span></span>
          </div>
          <div class="editor-mode" title="编辑模式(编辑、清洁、只读、表单)">编辑模式</div>
          <div>
            <div class="page-scale-minus" title="缩小(Ctrl+-)">
              <i></i>
            </div>
            <span class="page-scale-percentage" title="显示比例(点击可复原Ctrl+0)">100%</span>
            <div class="page-scale-add" title="放大(Ctrl+=)">
              <i></i>
            </div>
            <div class="paper-size">
              <i title="纸张类型"></i>
              <div class="options">
                <ul>
                  <li data-paper-size="794*1123" class="active">A4</li>
                  <li data-paper-size="1593*2251">A2</li>
                  <li data-paper-size="1125*1593">A3</li>
                  <li data-paper-size="565*796">A5</li>
                  <li data-paper-size="412*488">5号信封</li>
                  <li data-paper-size="450*866">6号信封</li>
                  <li data-paper-size="609*862">7号信封</li>
                  <li data-paper-size="862*1221">9号信封</li>
                  <li data-paper-size="813*1266">法律用纸</li>
                  <li data-paper-size="813*1054">信纸</li>
                </ul>
              </div>
            </div>
            <div class="paper-direction">
              <i title="纸张方向"></i>
              <div class="options">
                <ul>
                  <li data-paper-direction="vertical" class="active">纵向</li>
                  <li data-paper-direction="horizontal">横向</li>
                </ul>
              </div>
            </div>
            <div class="paper-margin" title="页边距">
              <i></i>
            </div>
            <div class="fullscreen" title="全屏显示">
              <i></i>
            </div>
          </div>
        </div>
      </el-footer>
    </el-container>
  </div>
</template>

<script>
import Editor from '@hufe921/canvas-editor'
import { Dialog } from './components/dialog/Dialog'
import { Signature } from './components/signature/Signature'
import { IEditorOption, ITableOption, IHeader, IFooter } from './options'

import {
  BlockType,
  Command,
  ControlType,
  EditorMode,
  EditorZone,
  ElementType,
  IBlock,
  ICatalogItem,
  IElement,
  KeyMap,
  ListStyle,
  ListType,
  PageMode,
  PaperDirection,
  RowFlex,
  TitleLevel,
  splitText
} from '@hufe921/canvas-editor'

export default {
  data() {
    return {
      // 间距列表
      spaceList: [
        {
          value: 1,
          label: 1
        },
        {
          value: 1.25,
          label: 1.25
        },
        {
          value: 1.5,
          label: 1.5
        },
        {
          value: 1.75,
          label: 1.75
        },
        {
          value: 2,
          label: 2
        },
        {
          value: 2.5,
          label: 2.5
        },
        {
          value: 3,
          label: 3
        }
      ],
      // 标题列表
      titleList: [
        {
          value: 'first',
          label: '标题1',
          size: 26
        },
        {
          value: 'second',
          label: '标题2',
          size: 24
        },
        {
          value: 'third',
          label: '标题3',
          size: 22
        },
        {
          value: 'fourth',
          label: '标题4',
          size: 20
        },
        {
          value: 'fifth',
          label: '标题5',
          size: 18
        },
        {
          value: 'sixth',
          label: '标题6',
          size: 16
        },
      ],
      // 字体列表
      fontFamilyList: [
        {
          value: 'Microsoft YaHei',
          label: '微软雅黑'
        },
        {
          value: '华文宋体',
          label: '华文宋体'
        },
        {
          value: '华文黑体',
          label: '华文黑体'
        },
        {
          value: '华文仿宋',
          label: '华文仿宋'
        },
        {
          value: '华文楷体',
          label: '华文楷体'
        },
        {
          value: '华文琥珀',
          label: '华文琥珀'
        },
        {
          value: '华文隶书',
          label: '华文隶书'
        },
        {
          value: '华文新魏',
          label: '华文新魏'
        },
        {
          value: '华文行楷',
          label: '华文行楷'
        },
        {
          value: '华文中宋',
          label: '华文中宋'
        },
        {
          value: '华文彩云',
          label: '华文彩云'
        },
        {
          value: 'Arial',
          label: 'Arial'
        },
        {
          value: 'Segoe UI',
          label: 'Segoe UI'
        },
        {
          value: 'Ink Free',
          label: 'Ink Free'
        },
        {
          value: 'Fantasy',
          label: 'Fantasy'
        }
      ],
      // 字号列表
      fontSizeList: [
        {
          value: 56,
          label: '初号'
        },
        {
          value: 48,
          label: '小初'
        },
        {
          value: 34,
          label: '一号'
        },
        {
          value: 32,
          label: '小一'
        },
        {
          value: 29,
          label: '二号'
        },
        {
          value: 24,
          label: '小二'
        },
        {
          value: 21,
          label: '三号'
        },
        {
          value: 20,
          label: '小三'
        },
        {
          value: 18,
          label: '四号'
        },
        {
          value: 16,
          label: '小四'
        },
        {
          value: 14,
          label: '五号'
        },
        {
          value: 12,
          label: '小五'
        },
        {
          value: 10,
          label: '六号'
        },
        {
          value: 8,
          label: '小六'
        },
        {
          value: 7,
          label: '七号'
        },
        {
          value: 6,
          label: '八号'
        },
      ],
      editorRef: null,
      isApple: typeof navigator !== 'undefined' && /Mac OS X/.test(navigator.userAgent),
      // 编辑模式
      modeList: [
        {
          mode: EditorMode.READONLY,
          name: '只读模式'
        },
        {
          mode: EditorMode.EDIT,
          name: '编辑模式'
        }
      ],
      data: {
        header: [],// 页眉配置
        main: [],// 主要编辑内容
        footer: [],// 页脚信息
      },
      options: {
        ...IEditorOption,
        // margins: [100, 120, 100, 120],
        width: 794,
        scale: 1.2
      },
      // 批注 TODO
      commentList: [],
      instance: null,
    };
  },
  props: {
    // 编辑模式
    editMode: {
      type: String,
    },
    // html数据
    htmlData: {
      type: String,
    },
    // 后端接口数据（用作回显）
    docJson: {
      type: String,
    }
  },
  watch: {
    editMode: { // 通过父组件传过来的编辑模式，设置top菜单栏
      handler(val) {
        this.editModeHandler(val)
      },
      deep: true
    },
    docJson: {
      deep: true,
      handler(newV) {
        this.data = JSON.parse(newV)
        this.instance?.destroy()
        this.init()
        this.editModeHandler(this.editMode)
      }
    },
  },
  mounted() {
    this.getScreen()
  },
  methods: {
    getScreen() {
      // let width = 794
      let margins = [100, 120, 100, 120]
      let scale = 1
      if(window?.innerWidth < 794) {
        // width = window?.innerWidth
        scale = window?.innerWidth / 794
        margins = margins.map(i => i * scale)
      }

      // this.options.width = width
      this.options.margins = margins
      this.options.scale = scale
    },
    editModeHandler(val) {
      if (this.editorRef) {
        this.editorRef.command.executeMode(val)
        // 设置模式
        const modeElement = document.querySelector('.editor-mode')
        modeElement.innerText = this.modeList.filter((item) => item.mode == val).map((data) => data.name) || ''
        // 设置菜单栏权限视觉反馈
        const isReadonly = val === EditorMode.READONLY
        const enableMenuList = ['search', 'print']
        document.querySelectorAll('.menu-item>div').forEach(dom => {
          const menu = dom.dataset.menu
          isReadonly && (!menu || !enableMenuList.includes(menu))
            ? dom.classList.add('disable')
            : dom.classList.remove('disable')
        })
      }
    },
    debounce(func, delay) {
      let timer;
      return function (...args) {
        if (timer) {
          window.clearTimeout(timer);
        }
        timer = window.setTimeout(() => {
          func.apply(this, args);
        }, delay);
      };
    },
    // 初始化
    init() {
      const isApple = typeof navigator !== 'undefined' && /Mac OS X/.test(navigator.userAgent)
      // 初始化实例
      const instance = this.instance = new Editor(
        document.querySelector('.canvas-editor'),
        this.data,
        this.options
      )
      this.editorRef = instance;
      // cypress使用
      Reflect.set(window, 'editor', instance)

      // 回显编辑器数据
      if (this.docJson !== null && this.docJson !== undefined) {
        // 通过getValue来的数据回显页面（因为用html回显页面会丢掉font-family，官网git issue有解释）
        instance.command.executeSetValue(JSON.parse(this.docJson))
        // instance.command.executeSetValue({main: JSON.parse(this.docJson)})
      } else {
        // 处理后端返回的html字符串
        // 先替换 \r\n 为 空格，以统一处理空格问题
        let step1 = this.htmlData.replace(/\r\n/g, ' ');
        // 然后替换 \\\" 为 \" ，确保样式字符串内的引号正确
        let step2 = step1.replace(/\\\"/g, '"');
        // 接着替换 \\ 为 空字符，去掉其他不必要的转义
        let cleanedHtml = step2.replace(/\\+/g, '');
        // 设置Word模板数据
        instance.command.executeSetHTML({ main: cleanedHtml })
      }

      // 菜单弹窗销毁
      window.addEventListener(
        'click',
        evt => {
          const visibleDom = document.querySelector('.visible')
          if (!visibleDom || visibleDom.contains(evt.target)) return
          visibleDom.classList.remove('visible')
        },
        {
          capture: true
        }
      )
      /*
        工具栏方法
      */

      //   console.log('elementList: ', payload)
      //   this.$emit('save', htmlVal)
      // }

      // 2. | 撤销 | 重做 | 格式刷 | 清除格式 |
      const undoDom = document.querySelector('.menu-item__undo')
      undoDom.title = `撤销(${isApple ? '⌘' : 'Ctrl'}+Z)`
      undoDom.onclick = function () {
        console.log('undo')
        instance.command.executeUndo()
      }

      const redoDom = document.querySelector('.menu-item__redo')
      redoDom.title = `重做(${isApple ? '⌘' : 'Ctrl'}+Y)`
      redoDom.onclick = function () {
        console.log('redo')
        instance.command.executeRedo()
      }

      const painterDom = document.querySelector(
        '.menu-item__painter'
      )
      painterDom.onclick = function () {
        console.log('painter')
        instance.command.executePainter({
          isDblclick: false
        })
      }
      painterDom.ondblclick = function () {
        console.log('painter')
        instance.command.executePainter({
          isDblclick: true
        })
      }

      document.querySelector('.menu-item__format').onclick =
        function () {
          // console.log('format')
          instance.command.executeFormat()
        }

      // 3. | 字体 | 字体变大 | 字体变小 | 加粗 | 斜体 | 下划线 | 删除线 | 上标 | 下标 | 字体颜色 | 背景色 |
      const fontDom = document.querySelector('.menu-item__font')
      const fontSelectDom = fontDom.querySelector('.select')
      const fontOptionDom = fontDom.querySelector('.options')
      fontDom.onclick = function () {
        // console.log('font')
        fontOptionDom.classList.toggle('visible')
      }
      fontOptionDom.onclick = function (evt) {
        const li = evt.target
        instance.command.executeFont(li.dataset.family)
      }

      const sizeSetDom = document.querySelector('.menu-item__size')
      const sizeSelectDom = sizeSetDom.querySelector('.select')
      const sizeOptionDom = sizeSetDom.querySelector('.options')
      sizeSetDom.title = `设置字号`
      sizeSetDom.onclick = function () {
        // console.log('size')
        sizeOptionDom.classList.toggle('visible')
      }
      sizeOptionDom.onclick = function (evt) {
        const li = evt.target
        instance.command.executeSize(Number(li.dataset.size))
      }

      const sizeAddDom = document.querySelector(
        '.menu-item__size-add'
      )
      sizeAddDom.title = `增大字号(${this.isApple ? '⌘' : 'Ctrl'}+[)`
      sizeAddDom.onclick = function () {
        console.log('size-add')
        instance.command.executeSizeAdd()
      }

      const sizeMinusDom = document.querySelector(
        '.menu-item__size-minus'
      )
      sizeMinusDom.title = `减小字号(${this.isApple ? '⌘' : 'Ctrl'}+])`
      sizeMinusDom.onclick = function () {
        console.log('size-minus')
        instance.command.executeSizeMinus()
      }

      const boldDom = document.querySelector('.menu-item__bold')
      boldDom.title = `加粗(${this.isApple ? '⌘' : 'Ctrl'}+B)`
      boldDom.onclick = function () {
        console.log('bold')
        instance.command.executeBold()
      }

      const italicDom =
        document.querySelector('.menu-item__italic')
      italicDom.title = `斜体(${this.isApple ? '⌘' : 'Ctrl'}+I)`
      italicDom.onclick = function () {
        console.log('italic')
        instance.command.executeItalic()
      }

      const underlineDom = document.querySelector(
        '.menu-item__underline'
      )
      underlineDom.title = `下划线(${this.isApple ? '⌘' : 'Ctrl'}+U)`
      underlineDom.onclick = function () {
        console.log('underline')
        instance.command.executeUnderline()
      }

      const strikeoutDom = document.querySelector(
        '.menu-item__strikeout'
      )
      strikeoutDom.onclick = function () {
        console.log('strikeout')
        instance.command.executeStrikeout()
      }

      const superscriptDom = document.querySelector(
        '.menu-item__superscript'
      )
      superscriptDom.title = `上标(${this.isApple ? '⌘' : 'Ctrl'}+Shift+,)`
      superscriptDom.onclick = function () {
        console.log('superscript')
        instance.command.executeSuperscript()
      }

      const subscriptDom = document.querySelector(
        '.menu-item__subscript'
      )
      subscriptDom.title = `下标(${this.isApple ? '⌘' : 'Ctrl'}+Shift+.)`
      subscriptDom.onclick = function () {
        console.log('subscript')
        instance.command.executeSubscript()
      }

      const colorControlDom = document.querySelector('#color')
      colorControlDom.oninput = function () {
        instance.command.executeColor(colorControlDom.value)
      }
      const colorDom = document.querySelector('.menu-item__color')
      const colorSpanDom = colorDom.querySelector('span')
      colorDom.onclick = function () {
        console.log('color')
        colorControlDom.click()
      }

      const highlightControlDom =
        document.querySelector('#highlight')
      highlightControlDom.oninput = function () {
        instance.command.executeHighlight(highlightControlDom.value)
      }
      const highlightDom = document.querySelector(
        '.menu-item__highlight'
      )
      const highlightSpanDom = highlightDom.querySelector('span')
      highlightDom.onclick = function () {
        console.log('highlight')
        highlightControlDom?.click()
      }

      const titleDom = document.querySelector('.menu-item__title')
      const titleSelectDom = titleDom.querySelector('.select')
      const titleOptionDom = titleDom.querySelector('.options')
      titleOptionDom.querySelectorAll('li').forEach((li, index) => {
        li.title = `Ctrl+${this.isApple ? 'Option' : 'Alt'}+${index}`
      })

      titleDom.onclick = function () {
        console.log('title')
        titleOptionDom.classList.toggle('visible')
      }
      titleOptionDom.onclick = function (evt) {
        const li = evt.target
        const level = li.dataset.level
        instance.command.executeTitle(level || null)
      }

      const leftDom = document.querySelector('.menu-item__left')
      leftDom.title = `左对齐(${this.isApple ? '⌘' : 'Ctrl'}+L)`
      leftDom.onclick = function () {
        console.log('left')
        instance.command.executeRowFlex(RowFlex.LEFT)
      }

      const centerDom =
        document.querySelector('.menu-item__center')
      centerDom.title = `居中对齐(${this.isApple ? '⌘' : 'Ctrl'}+E)`
      centerDom.onclick = function () {
        console.log('center')
        instance.command.executeRowFlex(RowFlex.CENTER)
      }

      const rightDom = document.querySelector('.menu-item__right')
      rightDom.title = `右对齐(${this.isApple ? '⌘' : 'Ctrl'}+R)`
      rightDom.onclick = function () {
        console.log('right')
        instance.command.executeRowFlex(RowFlex.RIGHT)
      }

      const alignmentDom = document.querySelector(
        '.menu-item__alignment'
      )
      alignmentDom.title = `两端对齐(${this.isApple ? '⌘' : 'Ctrl'}+J)`
      alignmentDom.onclick = function () {
        console.log('alignment')
        instance.command.executeRowFlex(RowFlex.ALIGNMENT)
      }

      const rowMarginDom = document.querySelector(
        '.menu-item__row-margin'
      )
      const rowOptionDom = rowMarginDom.querySelector('.options')
      rowMarginDom.onclick = function () {
        console.log('row-margin')
        rowOptionDom.classList.toggle('visible')
      }
      rowOptionDom.onclick = function (evt) {
        const li = evt.target
        instance.command.executeRowMargin(Number(li.dataset.rowmargin))
      }

      const listDom = document.querySelector('.menu-item__list')
      listDom.title = `列表(${this.isApple ? '⌘' : 'Ctrl'}+Shift+U)`
      const listOptionDom = listDom.querySelector('.options')
      listDom.onclick = function () {
        console.log('list')
        listOptionDom.classList.toggle('visible')
      }
      listOptionDom.onclick = function (evt) {
        const li = evt.target
        const listType = li.dataset.listType || null
        const listStyle = (li.dataset.listStyle)
        instance.command.executeList(listType, listStyle)
      }
      // 4. | 表格 | 图片 | 超链接 | 分割线 | 水印 | 代码块 | 分隔符 | 控件 | 复选框 | LaTeX | 日期选择器
      const tableDom = document.querySelector('.menu-item__table')
      const tablePanelContainer = document.querySelector('.menu-item__table__collapse')
      const tableClose = document.querySelector('.table-close')
      const tableTitle = document.querySelector('.table-select')
      const tablePanel = document.querySelector('.table-panel')
      // 绘制行列
      const tableCellList = []
      for (let i = 0; i < 10; i++) {
        const tr = document.createElement('tr')
        tr.classList.add('table-row')
        const trCellList = []
        for (let j = 0; j < 10; j++) {
          const td = document.createElement('td')
          td.classList.add('table-cel')
          tr.append(td)
          trCellList.push(td)
        }
        tablePanel.append(tr)
        tableCellList.push(trCellList)
      }
      let colIndex = 0
      let rowIndex = 0
      // 移除所有格选择
      function removeAllTableCellSelect() {
        tableCellList.forEach(tr => {
          tr.forEach(td => td.classList.remove('active'))
        })
      }
      // 设置标题内容
      function setTableTitle(payload) {
        tableTitle.innerText = payload
      }
      // 恢复初始状态
      function recoveryTable() {
        // 还原选择样式、标题、选择行列
        removeAllTableCellSelect()
        setTableTitle('插入')
        colIndex = 0
        rowIndex = 0
        // 隐藏panel
        tablePanelContainer.style.display = 'none'
      }
      tableDom.onclick = function () {
        console.log('table')
        tablePanelContainer.style.display = 'block'
      }
      tablePanel.onmousemove = function (evt) {
        const celSize = 16
        const rowMarginTop = 10
        const celMarginRight = 6
        const { offsetX, offsetY } = evt
        // 移除所有选择
        removeAllTableCellSelect()
        colIndex = Math.ceil(offsetX / (celSize + celMarginRight)) || 1
        rowIndex = Math.ceil(offsetY / (celSize + rowMarginTop)) || 1
        // 改变选择样式
        tableCellList.forEach((tr, trIndex) => {
          tr.forEach((td, tdIndex) => {
            if (tdIndex < colIndex && trIndex < rowIndex) {
              td.classList.add('active')
            }
          })
        })
        // 改变表格标题
        setTableTitle(`${rowIndex}×${colIndex}`)
      }
      tableClose.onclick = function () {
        recoveryTable()
      }
      tablePanel.onclick = function () {
        // 应用选择
        instance.command.executeInsertTable(rowIndex, colIndex)
        recoveryTable()
      }

      // const imageDom = document.querySelector('.menu-item__image')
      // const imageFileDom = document.querySelector('#image')
      // imageDom.onclick = function () {
      //   imageFileDom.click()
      // }
      // imageFileDom.onchange = function () {
      //   const file = imageFileDom.files[0]
      //   const fileReader = new FileReader()
      //   fileReader.readAsDataURL(file)
      //   fileReader.onload = function () {
      //     // 计算宽高
      //     const image = new Image()
      //     const value = String(fileReader.result)
      //     image.src = value
      //     image.onload = function () {
      //       instance.command.executeImage({
      //         value,
      //         width: image.width,
      //         height: image.height
      //       })
      //       imageFileDom.value = ''
      //     }
      //   }
      // }

      const hyperlinkDom = document.querySelector(
        '.menu-item__hyperlink'
      )
      hyperlinkDom.onclick = function () {
        console.log('hyperlink')
        new Dialog({
          title: '超链接',
          data: [
            {
              type: 'text',
              label: '文本',
              name: 'name',
              required: true,
              placeholder: '请输入文本',
              value: instance.command.getRangeText()
            },
            {
              type: 'text',
              label: '链接',
              name: 'url',
              required: true,
              placeholder: '请输入链接'
            }
          ],
          onConfirm: payload => {
            const name = payload.find(p => p.name === 'name')?.value
            if (!name) return
            const url = payload.find(p => p.name === 'url')?.value
            if (!url) return
            instance.command.executeHyperlink({
              type: ElementType.HYPERLINK,
              value: '',
              url,
              valueList: splitText(name).map(n => ({
                value: n,
                size: 16
              }))
            })
          }
        })
      }

      const separatorDom = document.querySelector(
        '.menu-item__separator'
      )
      const separatorOptionDom =
        separatorDom.querySelector('.options')
      separatorDom.onclick = function () {
        console.log('separator')
        separatorOptionDom.classList.toggle('visible')
      }
      separatorOptionDom.onmousedown = function (evt) {
        let payload = []
        const li = evt.target
        const separatorDash = li.dataset.separator?.split(',').map(Number)
        if (separatorDash) {
          const isSingleLine = separatorDash.every(d => d === 0)
          if (!isSingleLine) {
            payload = separatorDash
          }
        }
        instance.command.executeSeparator(payload)
      }

      // const pageBreakDom = document.querySelector(
      //   '.menu-item__page-break'
      // )
      // pageBreakDom.onclick = function () {
      //   console.log('pageBreak')
      //   instance.command.executePageBreak()
      // }

      // const watermarkDom = document.querySelector(
      //   '.menu-item__watermark'
      // )
      // const watermarkOptionDom =
      //   watermarkDom.querySelector('.options')
      // watermarkDom.onclick = function () {
      //   console.log('watermark')
      //   watermarkOptionDom.classList.toggle('visible')
      // }
      // watermarkOptionDom.onmousedown = function (evt) {
      //   const li = evt.target
      //   const menu = li.dataset.menu
      //   watermarkOptionDom.classList.toggle('visible')
      //   if (menu === 'add') {
      //     new Dialog({
      //       title: '水印',
      //       data: [
      //         {
      //           type: 'text',
      //           label: '内容',
      //           name: 'data',
      //           required: true,
      //           placeholder: '请输入内容'
      //         },
      //         {
      //           type: 'color',
      //           label: '颜色',
      //           name: 'color',
      //           required: true,
      //           value: '#AEB5C0'
      //         },
      //         {
      //           type: 'number',
      //           label: '字体大小',
      //           name: 'size',
      //           required: true,
      //           value: '120'
      //         }
      //       ],
      //       onConfirm: payload => {
      //         const nullableIndex = payload.findIndex(p => !p.value)
      //         if (~nullableIndex) return
      //         const watermark = payload.reduce((pre, cur) => {
      //           pre[cur.name] = cur.value
      //           return pre
      //         }, {})
      //         instance.command.executeAddWatermark({
      //           data: watermark.data,
      //           color: watermark.color,
      //           size: Number(watermark.size)
      //         })
      //       }
      //     })
      //   } else {
      //     instance.command.executeDeleteWatermark()
      //   }
      // }

      // const codeblockDom = document.querySelector(
      //   '.menu-item__codeblock'
      // )
      // codeblockDom.onclick = function () {
      //   console.log('codeblock')
      //   new Dialog({
      //     title: '代码块',
      //     data: [
      //       {
      //         type: 'textarea',
      //         name: 'codeblock',
      //         placeholder: '请输入代码',
      //         width: 500,
      //         height: 300
      //       }
      //     ],
      //     onConfirm: payload => {
      //       const codeblock = payload.find(p => p.name === 'codeblock')?.value
      //       if (!codeblock) return
      //       const tokenList = prism.tokenize(codeblock, prism.languages.javascript)
      //       const formatTokenList = formatPrismToken(tokenList)
      //       const elementList = []
      //       for (let i = 0; i < formatTokenList.length; i++) {
      //         const formatToken = formatTokenList[i]
      //         const tokenStringList = splitText(formatToken.content)
      //         for (let j = 0; j < tokenStringList.length; j++) {
      //           const value = tokenStringList[j]
      //           const element = {
      //             value
      //           }
      //           if (formatToken.color) {
      //             element.color = formatToken.color
      //           }
      //           if (formatToken.bold) {
      //             element.bold = true
      //           }
      //           if (formatToken.italic) {
      //             element.italic = true
      //           }
      //           elementList.push(element)
      //         }
      //       }
      //       elementList.unshift({
      //         value: '\n'
      //       })
      //       instance.command.executeInsertElementList(elementList)
      //     }
      //   })
      // }

      // const controlDom = document.querySelector(
      //   '.menu-item__control'
      // )
      // const controlOptionDom = controlDom.querySelector('.options')
      // controlDom.onclick = function () {
      //   console.log('control')
      //   controlOptionDom.classList.toggle('visible')
      // }
      // controlOptionDom.onmousedown = function (evt) {
      //   controlOptionDom.classList.toggle('visible')
      //   const li = evt.target
      //   const type = li.dataset.control
      //   switch (type) {
      //     case ControlType.TEXT:
      //       new Dialog({
      //         title: '文本控件',
      //         data: [
      //           {
      //             type: 'text',
      //             label: '占位符',
      //             name: 'placeholder',
      //             required: true,
      //             placeholder: '请输入占位符'
      //           },
      //           {
      //             type: 'text',
      //             label: '默认值',
      //             name: 'value',
      //             placeholder: '请输入默认值'
      //           }
      //         ],
      //         onConfirm: payload => {
      //           const placeholder = payload.find(
      //             p => p.name === 'placeholder'
      //           )?.value
      //           if (!placeholder) return
      //           const value = payload.find(p => p.name === 'value')?.value || ''
      //           instance.command.executeInsertElementList([
      //             {
      //               type: ElementType.CONTROL,
      //               value: '',
      //               control: {
      //                 type,
      //                 value: value
      //                   ? [
      //                       {
      //                         value
      //                       }
      //                     ]
      //                   : null,
      //                 placeholder
      //               }
      //             }
      //           ])
      //         }
      //       })
      //       break
      //     case ControlType.SELECT:
      //       new Dialog({
      //         title: '列举控件',
      //         data: [
      //           {
      //             type: 'text',
      //             label: '占位符',
      //             name: 'placeholder',
      //             required: true,
      //             placeholder: '请输入占位符'
      //           },
      //           {
      //             type: 'text',
      //             label: '默认值',
      //             name: 'code',
      //             placeholder: '请输入默认值'
      //           },
      //           {
      //             type: 'textarea',
      //             label: '值集',
      //             name: 'valueSets',
      //             required: true,
      //             height: 100,
      //             placeholder: `请输入值集JSON，例：\n[{\n"value":"有",\n"code":"98175"\n}]`
      //           }
      //         ],
      //         onConfirm: payload => {
      //           const placeholder = payload.find(
      //             p => p.name === 'placeholder'
      //           )?.value
      //           if (!placeholder) return
      //           const valueSets = payload.find(p => p.name === 'valueSets')?.value
      //           if (!valueSets) return
      //           const code = payload.find(p => p.name === 'code')?.value
      //           instance.command.executeInsertElementList([
      //             {
      //               type: ElementType.CONTROL,
      //               value: '',
      //               control: {
      //                 type,
      //                 code,
      //                 value: null,
      //                 placeholder,
      //                 valueSets: JSON.parse(valueSets)
      //               }
      //             }
      //           ])
      //         }
      //       })
      //       break
      //     case ControlType.CHECKBOX:
      //       new Dialog({
      //         title: '复选框控件',
      //         data: [
      //           {
      //             type: 'text',
      //             label: '默认值',
      //             name: 'code',
      //             placeholder: '请输入默认值，多个值以英文逗号分割'
      //           },
      //           {
      //             type: 'textarea',
      //             label: '值集',
      //             name: 'valueSets',
      //             required: true,
      //             height: 100,
      //             placeholder: `请输入值集JSON，例：\n[{\n"value":"有",\n"code":"98175"\n}]`
      //           }
      //         ],
      //         onConfirm: payload => {
      //           const valueSets = payload.find(p => p.name === 'valueSets')?.value
      //           if (!valueSets) return
      //           const code = payload.find(p => p.name === 'code')?.value
      //           instance.command.executeInsertElementList([
      //             {
      //               type: ElementType.CONTROL,
      //               value: '',
      //               control: {
      //                 type,
      //                 code,
      //                 value: null,
      //                 valueSets: JSON.parse(valueSets)
      //               }
      //             }
      //           ])
      //         }
      //       })
      //       break
      //     default:
      //       break
      //   }
      // }

      // const checkboxDom = document.querySelector(
      //   '.menu-item__checkbox'
      // )
      // checkboxDom.onclick = function () {
      //   console.log('checkbox')
      //   instance.command.executeInsertElementList([
      //     {
      //       type: ElementType.CHECKBOX,
      //       checkbox: {
      //         value: false
      //       },
      //       value: ''
      //     }
      //   ])
      // }

      // const latexDom = document.querySelector('.menu-item__latex')
      // latexDom.onclick = function () {
      //   console.log('LaTeX')
      //   new Dialog({
      //     title: 'LaTeX',
      //     data: [
      //       {
      //         type: 'textarea',
      //         height: 100,
      //         name: 'value',
      //         placeholder: '请输入LaTeX文本'
      //       }
      //     ],
      //     onConfirm: payload => {
      //       const value = payload.find(p => p.name === 'value')?.value
      //       if (!value) return
      //       instance.command.executeInsertElementList([
      //         {
      //           type: ElementType.LATEX,
      //           value
      //         }
      //       ])
      //     }
      //   })
      // }

      // const dateDom = document.querySelector('.menu-item__date')
      // const dateDomOptionDom = dateDom.querySelector('.options')
      // dateDom.onclick = function () {
      //   console.log('date')
      //   dateDomOptionDom.classList.toggle('visible')
      //   // 定位调整
      //   const bodyRect = document.body.getBoundingClientRect()
      //   const dateDomOptionRect = dateDomOptionDom.getBoundingClientRect()
      //   if (dateDomOptionRect.left + dateDomOptionRect.width > bodyRect.width) {
      //     dateDomOptionDom.style.right = '0px'
      //     dateDomOptionDom.style.left = 'unset'
      //   } else {
      //     dateDomOptionDom.style.right = 'unset'
      //     dateDomOptionDom.style.left = '0px'
      //   }
      //   // 当前日期
      //   const date = new Date()
      //   const year = date.getFullYear().toString()
      //   const month = (date.getMonth() + 1).toString().padStart(2, '0')
      //   const day = date.getDate().toString().padStart(2, '0')
      //   const hour = date.getHours().toString().padStart(2, '0')
      //   const minute = date.getMinutes().toString().padStart(2, '0')
      //   const second = date.getSeconds().toString().padStart(2, '0')
      //   const dateString = `${year}-${month}-${day}`
      //   const dateTimeString = `${dateString} ${hour}:${minute}:${second}`
      //   dateDomOptionDom.querySelector('li:first-child').innerText = dateString
      //   dateDomOptionDom.querySelector('li:last-child').innerText = dateTimeString
      // }
      // dateDomOptionDom.onmousedown = function (evt) {
      //   const li = evt.target
      //   const dateFormat = li.dataset.format
      //   dateDomOptionDom.classList.toggle('visible')
      //   instance.command.executeInsertElementList([
      //     {
      //       type: ElementType.DATE,
      //       value: '',
      //       dateFormat,
      //       valueList: [
      //         {
      //           value: li.innerText.trim()
      //         }
      //       ]
      //     }
      //   ])
      // }

      // const blockDom = document.querySelector('.menu-item__block')
      // blockDom.onclick = function () {
      //   console.log('block')
      //   new Dialog({
      //     title: '内容块',
      //     data: [
      //       {
      //         type: 'select',
      //         label: '类型',
      //         name: 'type',
      //         value: 'iframe',
      //         required: true,
      //         options: [
      //           {
      //             label: '网址',
      //             value: 'iframe'
      //           },
      //           {
      //             label: '视频',
      //             value: 'video'
      //           }
      //         ]
      //       },
      //       {
      //         type: 'number',
      //         label: '宽度',
      //         name: 'width',
      //         placeholder: '请输入宽度（默认页面内宽度）'
      //       },
      //       {
      //         type: 'number',
      //         label: '高度',
      //         name: 'height',
      //         required: true,
      //         placeholder: '请输入高度'
      //       },
      //       {
      //         type: 'textarea',
      //         label: '地址',
      //         height: 100,
      //         name: 'value',
      //         required: true,
      //         placeholder: '请输入地址'
      //       }
      //     ],
      //     onConfirm: payload => {
      //       const type = payload.find(p => p.name === 'type')?.value
      //       if (!type) return
      //       const value = payload.find(p => p.name === 'value')?.value
      //       if (!value) return
      //       const width = payload.find(p => p.name === 'width')?.value
      //       const height = payload.find(p => p.name === 'height')?.value
      //       if (!height) return
      //       const block = {
      //         type: null
      //       }
      //       if (block.type === BlockType.IFRAME) {
      //         block.iframeBlock = {
      //           src: value
      //         }
      //       } else if (block.type === BlockType.VIDEO) {
      //         block.videoBlock = {
      //           src: value
      //         }
      //       }
      //       const blockElemen = {
      //         type: ElementType.BLOCK,
      //         value: '',
      //         height: Number(height),
      //         block
      //       }
      //       if (width) {
      //         blockElement.width = Number(width)
      //       }
      //       instance.command.executeInsertElementList([blockElement])
      //     }
      //   })
      // }

      // 5. | 搜索&替换 | 打印 |
      const searchCollapseDom = document.querySelector(
        '.menu-item__search__collapse'
      )
      const searchInputDom = document.querySelector(
        '.menu-item__search__collapse__search input'
      )
      const replaceInputDom = document.querySelector(
        '.menu-item__search__collapse__replace input'
      )
      const searchDom =
        document.querySelector('.menu-item__search')
      searchDom.title = `搜索与替换(${isApple ? '⌘' : 'Ctrl'}+F)`
      const searchResultDom =
        searchCollapseDom.querySelector('.search-result')
      function setSearchResult() {
        const result = instance.command.getSearchNavigateInfo()
        if (result) {
          const { index, count } = result
          searchResultDom.innerText = `${index}/${count}`
        } else {
          searchResultDom.innerText = ''
        }
      }
      searchDom.onclick = function () {
        // console.log('search')
        searchCollapseDom.style.display = 'block'
        const bodyRect = document.body.getBoundingClientRect()
        const searchRect = searchDom.getBoundingClientRect()
        const searchCollapseRect = searchCollapseDom.getBoundingClientRect()
        if (searchRect.left + searchCollapseRect.width > bodyRect.width) {
          searchCollapseDom.style.right = '0px'
          searchCollapseDom.style.left = 'unset'
        } else {
          searchCollapseDom.style.right = 'unset'
        }
        searchInputDom.focus()
      }
      searchCollapseDom.querySelector('span').onclick =
        function () {
          searchCollapseDom.style.display = 'none'
          searchInputDom.value = ''
          replaceInputDom.value = ''
          instance.command.executeSearch(null)
          setSearchResult()
        }
      searchInputDom.oninput = function () {
        instance.command.executeSearch(searchInputDom.value || null)
        setSearchResult()
      }
      searchInputDom.onkeydown = function (evt) {
        if (evt.key === 'Enter') {
          instance.command.executeSearch(searchInputDom.value || null)
          setSearchResult()
        }
      }
      searchCollapseDom.querySelector('button').onclick =
        function () {
          const searchValue = searchInputDom.value
          const replaceValue = replaceInputDom.value
          if (searchValue && replaceValue && searchValue !== replaceValue) {
            instance.command.executeReplace(replaceValue)
          }
        }
      searchCollapseDom.querySelector('.arrow-left').onclick =
        function () {
          instance.command.executeSearchNavigatePre()
          setSearchResult()
        }
      searchCollapseDom.querySelector('.arrow-right').onclick =
        function () {
          instance.command.executeSearchNavigateNext()
          setSearchResult()
        }

      const printDom = document.querySelector('.menu-item__print')
      printDom.title = `打印(${isApple ? '⌘' : 'Ctrl'}+P)`
      printDom.onclick = function () {
        console.log('print')
        instance.command.executePrint()
      }

      // 6. 目录显隐 | 页面模式 | 纸张缩放 | 纸张大小 | 纸张方向 | 页边距 | 全屏
      // async function updateCatalog() {
      //   const catalog = await instance.command.getCatalog()
      //   const catalogMainDom =
      //     document.querySelector('.catalog__main')
      //   catalogMainDom.innerHTML = ''
      //   if (catalog) {
      //     const appendCatalog = (
      //       parent,
      //       catalogItems
      //     ) => {
      //       for (let c = 0; c < catalogItems.length; c++) {
      //         const catalogItem = catalogItems[c]
      //         const catalogItemDom = document.createElement('div')
      //         catalogItemDom.classList.add('catalog-item')
      //         // 渲染
      //         const catalogItemContentDom = document.createElement('div')
      //         catalogItemContentDom.classList.add('catalog-item__content')
      //         const catalogItemContentSpanDom = document.createElement('span')
      //         catalogItemContentSpanDom.innerText = catalogItem.name
      //         catalogItemContentDom.append(catalogItemContentSpanDom)
      //         // 定位
      //         catalogItemContentDom.onclick = () => {
      //           instance.command.executeLocationCatalog(catalogItem.id)
      //         }
      //         catalogItemDom.append(catalogItemContentDom)
      //         if (catalogItem.subCatalog && catalogItem.subCatalog.length) {
      //           appendCatalog(catalogItemDom, catalogItem.subCatalog)
      //         }
      //         // 追加
      //         parent.append(catalogItemDom)
      //       }
      //     }
      //     appendCatalog(catalogMainDom, catalog)
      //   }
      // }
      // let isCatalogShow = true
      // const catalogDom = document.querySelector('.catalog')
      // const catalogModeDom =
      //   document.querySelector('.catalog-mode')
      // const catalogHeaderCloseDom = document.querySelector(
      //   '.catalog__header__close'
      // )
      // const switchCatalog = () => {
      //   console.log('目录', isCatalogShow)
      //   isCatalogShow = !isCatalogShow
      //   if (isCatalogShow) {
      //     console.log('目录', isCatalogShow)
      //     catalogDom.style.display = 'block'
      //     updateCatalog()
      //   } else {
      //     catalogDom.style.display = 'none'
      //   }
      // }
      // catalogModeDom.onclick = switchCatalog
      // catalogHeaderCloseDom.onclick = switchCatalog

      const pageModeDom = document.querySelector('.page-mode')
      const pageModeOptionsDom =
        pageModeDom.querySelector('.options')
      pageModeDom.onclick = function () {
        pageModeOptionsDom.classList.toggle('visible')
      }
      pageModeOptionsDom.onclick = function (evt) {
        const li = evt.target
        instance.command.executePageMode(li.dataset.pageMode)
      }

      document.querySelector('.page-scale-percentage').onclick =
        function () {
          console.log('page-scale-recovery')
          instance.command.executePageScaleRecovery()
        }

      document.querySelector('.page-scale-minus').onclick =
        function () {
          console.log('page-scale-minus')
          instance.command.executePageScaleMinus()
        }

      document.querySelector('.page-scale-add').onclick =
        function () {
          console.log('page-scale-add')
          instance.command.executePageScaleAdd()
        }

      // 纸张大小
      const paperSizeDom = document.querySelector('.paper-size')
      const paperSizeDomOptionsDom =
        paperSizeDom.querySelector('.options')
      paperSizeDom.onclick = function () {
        paperSizeDomOptionsDom.classList.toggle('visible')
      }
      paperSizeDomOptionsDom.onclick = function (evt) {
        const li = evt.target
        const paperType = li.dataset.paperSize
        const [width, height] = paperType.split('*').map(Number)
        instance.command.executePaperSize(width, height)
        // 纸张状态回显
        paperSizeDomOptionsDom
          .querySelectorAll('li')
          .forEach(child => child.classList.remove('active'))
        li.classList.add('active')
      }

      // 纸张方向
      const paperDirectionDom =
        document.querySelector('.paper-direction')
      const paperDirectionDomOptionsDom =
        paperDirectionDom.querySelector('.options')
      paperDirectionDom.onclick = function () {
        paperDirectionDomOptionsDom.classList.toggle('visible')
      }
      paperDirectionDomOptionsDom.onclick = function (evt) {
        const li = evt.target
        const paperDirection = li.dataset.paperDirection
        instance.command.executePaperDirection(paperDirection)
        // 纸张方向状态回显
        paperDirectionDomOptionsDom
          .querySelectorAll('li')
          .forEach(child => child.classList.remove('active'))
        li.classList.add('active')
      }

      // 页面边距
      const paperMarginDom =
        document.querySelector('.paper-margin')
      paperMarginDom.onclick = function () {
        const [topMargin, rightMargin, bottomMargin, leftMargin] =
          instance.command.getPaperMargin()
        new Dialog({
          title: '页边距',
          data: [
            {
              type: 'text',
              label: '上边距',
              name: 'top',
              required: true,
              value: `${topMargin}`,
              placeholder: '请输入上边距'
            },
            {
              type: 'text',
              label: '下边距',
              name: 'bottom',
              required: true,
              value: `${bottomMargin}`,
              placeholder: '请输入下边距'
            },
            {
              type: 'text',
              label: '左边距',
              name: 'left',
              required: true,
              value: `${leftMargin}`,
              placeholder: '请输入左边距'
            },
            {
              type: 'text',
              label: '右边距',
              name: 'right',
              required: true,
              value: `${rightMargin}`,
              placeholder: '请输入右边距'
            }
          ],
          onConfirm: payload => {
            const top = payload.find(p => p.name === 'top')?.value
            if (!top) return
            const bottom = payload.find(p => p.name === 'bottom')?.value
            if (!bottom) return
            const left = payload.find(p => p.name === 'left')?.value
            if (!left) return
            const right = payload.find(p => p.name === 'right')?.value
            if (!right) return
            instance.command.executeSetPaperMargin([
              Number(top),
              Number(right),
              Number(bottom),
              Number(left)
            ])
          }
        })
      }

      // 全屏
      const fullscreenDom = document.querySelector('.fullscreen')
      fullscreenDom.onclick = toggleFullscreen
      window.addEventListener('keydown', evt => {
        if (evt.key === 'F11') {
          toggleFullscreen()
          evt.preventDefault()
        }
      })
      document.addEventListener('fullscreenchange', () => {
        fullscreenDom.classList.toggle('exist')
      })
      function toggleFullscreen() {
        console.log('fullscreen')
        if (!document.fullscreenElement) {
          document.documentElement.requestFullscreen()
        } else {
          document.exitFullscreen()
        }
      }

      // 7. 编辑器使用模式
      let modeIndex = 0
      const modeList = [{
        mode: EditorMode.READONLY,
        name: '只读模式'
      },
      {
        mode: EditorMode.EDIT,
        name: '编辑模式'
      },
      {
        mode: EditorMode.CLEAN,
        name: '清洁模式'
      },

      {
        mode: EditorMode.FORM,
        name: '表单模式'
      },
      {
        mode: EditorMode.PRINT,
        name: '打印模式'
      }
      ]
      const modeElement = document.querySelector('.editor-mode')
      // 初始设置只读模式
      const { name, mode } = modeList[modeIndex]
      modeElement.innerText = name
      instance.command.executeMode(mode)
      // 设置菜单栏权限视觉反馈
      const isReadonly = mode === EditorMode.READONLY
      const enableMenuList = ['search', 'print']
      document.querySelectorAll('.menu-item>div').forEach(dom => {
        const menu = dom.dataset.menu
        isReadonly && (!menu || !enableMenuList.includes(menu))
          ? dom.classList.add('disable')
          : dom.classList.remove('disable')
      })
      // modeElement.onclick = function () {
      //   // 模式选择循环
      //   modeIndex === modeList.length - 1 ? (modeIndex = 0) : modeIndex++
      //   // 设置模式
      //   const { name, mode } = modeList[modeIndex]
      //   modeElement.innerText = name
      //   console.log(1212, name)
      //   instance.command.executeMode(mode)
      //   // 设置菜单栏权限视觉反馈
      //   const isReadonly = mode === EditorMode.READONLY
      //   const enableMenuList = ['search', 'print']
      //   document.querySelectorAll('.menu-item>div').forEach(dom => {
      //     const menu = dom.dataset.menu
      //     isReadonly && (!menu || !enableMenuList.includes(menu))
      //       ? dom.classList.add('disable')
      //       : dom.classList.remove('disable')
      //   })
      // }

      // 模拟批注
      // const commentDom = document.querySelector('.comment')
      // const updateComment = async() => {
      //   const groupIds = await instance.command.getGroupIds()
      //   for (const comment of this.commentList) {
      //     const activeCommentDom = commentDom.querySelector(
      //       `.comment-item[data-id='${comment.id}']`
      //     )
      //     // 编辑器是否存在对应成组id
      //     if (!groupIds.includes(comment.id)) {
      //       // 当前dom是否存在-不存在则追加
      //       if (!activeCommentDom) {
      //         const commentItem = document.createElement('div')
      //         commentItem.classList.add('comment-item')
      //         commentItem.setAttribute('data-id', comment.id)
      //         commentItem.onclick = () => {
      //           instance.command.executeLocationGroup(comment.id)
      //         }
      //         commentDom.append(commentItem)
      //         // 选区信息
      //         const commentItemTitle = document.createElement('div')
      //         commentItemTitle.classList.add('comment-item__title')
      //         commentItemTitle.append(document.createElement('span'))
      //         const commentItemTitleContent = document.createElement('span')
      //         commentItemTitleContent.innerText = comment.rangeText
      //         commentItemTitle.append(commentItemTitleContent)
      //         const closeDom = document.createElement('i')
      //         closeDom.onclick = () => {
      //           instance.command.executeDeleteGroup(comment.id)
      //         }
      //         commentItemTitle.append(closeDom)
      //         commentItem.append(commentItemTitle)
      //         // 基础信息
      //         const commentItemInfo = document.createElement('div')
      //         commentItemInfo.classList.add('comment-item__info')
      //         const commentItemInfoName = document.createElement('span')
      //         commentItemInfoName.innerText = comment.userName
      //         const commentItemInfoDate = document.createElement('span')
      //         commentItemInfoDate.innerText = comment.createdDate
      //         commentItemInfo.append(commentItemInfoName)
      //         commentItemInfo.append(commentItemInfoDate)
      //         commentItem.append(commentItemInfo)
      //         // 详细评论
      //         const commentItemContent = document.createElement('div')
      //         commentItemContent.classList.add('comment-item__content')
      //         commentItemContent.innerText = comment.content
      //         commentItem.append(commentItemContent)
      //         commentDom.append(commentItem)
      //       }
      //     } else {
      //       // 编辑器内不存在对应成组id则dom则移除
      //       activeCommentDom?.remove()
      //     }
      //   }
      // }
      // 8. 内部事件监听
      instance.listener.rangeStyleChange = function (payload) {
        // 控件类型
        payload.type === ElementType.SUBSCRIPT
          ? subscriptDom.classList.add('active')
          : subscriptDom.classList.remove('active')
        payload.type === ElementType.SUPERSCRIPT
          ? superscriptDom.classList.add('active')
          : superscriptDom.classList.remove('active')
        payload.type === ElementType.SEPARATOR
          ? separatorDom.classList.add('active')
          : separatorDom.classList.remove('active')
        separatorOptionDom
          .querySelectorAll('li')
          .forEach(li => li.classList.remove('active'))
        if (payload.type === ElementType.SEPARATOR) {
          const separator = payload.dashArray.join(',') || '0,0'
          const curSeparatorDom = separatorOptionDom.querySelector(
            `[data-separator='${separator}']`
          )
          if (curSeparatorDom) {
            curSeparatorDom.classList.add('active')
          }
        }

        // 富文本
        fontOptionDom.querySelectorAll('li').forEach(li => li.classList.remove('active'))
        const curFontDom = fontOptionDom.querySelector(
          `[data-family='${payload.font}']`
        )
        if (curFontDom) {
          fontSelectDom.innerText = curFontDom.innerText
          fontSelectDom.style.fontFamily = payload.font
          curFontDom.classList.add('active')
        }
        sizeOptionDom
          .querySelectorAll('li')
          .forEach(li => li.classList.remove('active'))
        const curSizeDom = sizeOptionDom.querySelector(
          `[data-size='${payload.size}']`
        )
        if (curSizeDom) {
          sizeSelectDom.innerText = curSizeDom.innerText
          curSizeDom.classList.add('active')
        } else {
          sizeSelectDom.innerText = `${payload.size}`
        }
        payload.bold
          ? boldDom.classList.add('active')
          : boldDom.classList.remove('active')
        payload.italic
          ? italicDom.classList.add('active')
          : italicDom.classList.remove('active')
        payload.underline
          ? underlineDom.classList.add('active')
          : underlineDom.classList.remove('active')
        payload.strikeout
          ? strikeoutDom.classList.add('active')
          : strikeoutDom.classList.remove('active')
        if (payload.color) {
          colorDom.classList.add('active')
          colorControlDom.value = payload.color
          colorSpanDom.style.backgroundColor = payload.color
        } else {
          colorDom.classList.remove('active')
          colorControlDom.value = '#000000'
          colorSpanDom.style.backgroundColor = '#000000'
        }
        if (payload.highlight) {
          highlightDom.classList.add('active')
          highlightControlDom.value = payload.highlight
          highlightSpanDom.style.backgroundColor = payload.highlight
        } else {
          highlightDom.classList.remove('active')
          highlightControlDom.value = '#ffff00'
          highlightSpanDom.style.backgroundColor = '#ffff00'
        }

        // 行布局
        leftDom.classList.remove('active')
        centerDom.classList.remove('active')
        rightDom.classList.remove('active')
        alignmentDom.classList.remove('active')
        if (payload.rowFlex && payload.rowFlex === 'right') {
          rightDom.classList.add('active')
        } else if (payload.rowFlex && payload.rowFlex === 'center') {
          centerDom.classList.add('active')
        } else if (payload.rowFlex && payload.rowFlex === 'alignment') {
          alignmentDom.classList.add('active')
        } else {
          leftDom.classList.add('active')
        }

        // 行间距
        rowOptionDom
          .querySelectorAll('li')
          .forEach(li => li.classList.remove('active'))
        const curRowMarginDom = rowOptionDom.querySelector(
          `[data-rowmargin='${payload.rowMargin}']`
        )
        curRowMarginDom.classList.add('active')

        // 功能
        payload.undo
          ? undoDom.classList.remove('no-allow')
          : undoDom.classList.add('no-allow')
        payload.redo
          ? redoDom.classList.remove('no-allow')
          : redoDom.classList.add('no-allow')
        payload.painter
          ? painterDom.classList.add('active')
          : painterDom.classList.remove('active')

        // 标题
        titleOptionDom
          .querySelectorAll('li')
          .forEach(li => li.classList.remove('active'))
        if (payload.level) {
          const curTitleDom = titleOptionDom.querySelector(
            `[data-level='${payload.level}']`
          )
          titleSelectDom.innerText = curTitleDom.innerText
          curTitleDom.classList.add('active')
        } else {
          titleSelectDom.innerText = '正文'
          titleOptionDom.querySelector('li:first-child').classList.add('active')
        }

        // 列表
        listOptionDom
          .querySelectorAll('li')
          .forEach(li => li.classList.remove('active'))
        if (payload.listType) {
          listDom.classList.add('active')
          const listType = payload.listType
          const listStyle =
            payload.listType === ListType.OL ? ListStyle.DECIMAL : payload.listType
          const curListDom = listOptionDom.querySelector(
            `[data-list-type='${listType}'][data-list-style='${listStyle}']`
          )
          if (curListDom) {
            curListDom.classList.add('active')
          }
        } else {
          listDom.classList.remove('active')
        }

        // 批注
        // commentDom
        //   .querySelectorAll('.comment-item')
        //   .forEach(commentItemDom => {
        //     commentItemDom.classList.remove('active')
        //   })
        // if (payload.groupIds) {
        //   const [id] = payload.groupIds
        //   const activeCommentDom = commentDom.querySelector(
        //     `.comment-item[data-id='${id}']`
        //   )
        //   if (activeCommentDom) {
        //     activeCommentDom.classList.add('active')
        //     scrollIntoView(commentDom, activeCommentDom)
        //   }
        // }
      }

      instance.listener.visiblePageNoListChange = function (payload) {
        const text = payload.map(i => i + 1).join('、')
        document.querySelector('.page-no-list').innerText = text
      }

      instance.listener.pageSizeChange = function (payload) {
        if (document.querySelector('.page-size')) {
          document.querySelector(
            '.page-size'
          ).innerText = payload.toString()
        }
      }

      instance.listener.intersectionPageNoChange = function (payload) {
        document.querySelector('.page-no').innerText = `${payload + 1
          }`
      }

      instance.listener.pageScaleChange = function (payload) {
        document.querySelector(
          '.page-scale-percentage'
        ).innerText = `${Math.floor(payload * 10 * 10)}%`
      }

      instance.listener.controlChange = function (payload) {
        const disableMenusInControlContext = [
          'table',
          'hyperlink',
          'separator',
          'page-break'
        ]
        // 菜单操作权限
        disableMenusInControlContext.forEach(menu => {
          const menuDom = document.querySelector(
            `.menu-item__${menu}`
          )
          payload
            ? menuDom.classList.add('disable')
            : menuDom.classList.remove('disable')
        })
      }

      instance.listener.pageModeChange = function (payload) {
        const activeMode = pageModeOptionsDom.querySelector(
          `[data-page-mode='${payload}']`
        )
        pageModeOptionsDom
          .querySelectorAll('li')
          .forEach(li => li.classList.remove('active'))
        activeMode.classList.add('active')
      }

      const handleContentChange = async () => {
        this.$emit('isSave', true)
        // 字数
        const wordCount = await instance.command.getWordCount()
        document.querySelector('.word-count').innerText = `${wordCount || 0
          }`
        // 目录
        // if (isCatalogShow) {
        //   this.$nextTick(() => {
        //     updateCatalog()
        //   })
        // }
        // // 批注
        // this.$nextTick(() => {
        //   updateComment()
        // })
      }
      instance.listener.contentChange = this.debounce(handleContentChange, 200)
      handleContentChange()


      // 9. 右键菜单注册
      instance.register.contextMenuList([
        {
          name: '批注',
          when: payload => {
            return (
              !payload.isReadonly &&
              payload.editorHasSelection &&
              payload.zone === EditorZone.MAIN
            )
          },
          callback: (command) => {
            new Dialog({
              title: '批注',
              data: [
                {
                  type: 'textarea',
                  label: '批注',
                  height: 100,
                  name: 'value',
                  required: true,
                  placeholder: '请输入批注'
                }
              ],
              onConfirm: payload => {
                const value = payload.find(p => p.name === 'value')?.value
                if (!value) return
                const groupId = command.executeSetGroup()
                if (!groupId) return
                commentList.push({
                  id: groupId,
                  content: value,
                  userName: 'Hufe',
                  rangeText: command.getRangeText(),
                  createdDate: new Date().toLocaleString()
                })
              }
            })
          }
        },
        {
          name: '签名',
          icon: 'signature',
          when: payload => {
            return !payload.isReadonly && payload.editorTextFocus
          },
          callback: (command) => {
            new Signature({
              onConfirm(payload) {
                if (!payload) return
                const { value, width, height } = payload
                if (!value || !width || !height) return
                command.executeInsertElementList([
                  {
                    value,
                    width,
                    height,
                    type: ElementType.IMAGE
                  }
                ])
              }
            })
          }
        },
        {
          name: '格式整理',
          icon: 'word-tool',
          when: payload => {
            return !payload.isReadonly
          },
          callback: (command) => {
            command.executeWordTool()
          }
        }
      ])


      // 10. 快捷键注册
      instance.register.shortcutList([
        {
          key: KeyMap.P,
          mod: true,
          isGlobal: true,
          callback: (command) => {
            command.executePrint()
          }
        },
        {
          key: KeyMap.F,
          mod: true,
          isGlobal: true,
          callback: (command) => {
            const text = command.getRangeText()
            searchDom.click()
            if (text) {
              searchInputDom.value = text
              instance.command.executeSearch(text)
              setSearchResult()
            }
          }
        },
        {
          key: KeyMap.MINUS,
          ctrl: true,
          isGlobal: true,
          callback: (command) => {
            command.executePageScaleMinus()
          }
        },
        {
          key: KeyMap.EQUAL,
          ctrl: true,
          isGlobal: true,
          callback: (command) => {
            command.executePageScaleAdd()
          }
        },
        {
          key: KeyMap.ZERO,
          ctrl: true,
          isGlobal: true,
          callback: (command) => {
            command.executePageScaleRecovery()
          }
        }
      ])
    },
  },
  beforeDestroy() {
    if (this.instance) {
      this.instance.destroy()
      this.instance = null
    }
  },
  // mounted() {
  //   this.init()
  // }
};
</script>

<style lang="scss" scoped>
@import url('./components/dialog/dialog.css');
@import url('./components/signature/signature.css');
//@import url('./style.css');

.footer {
  position: static;
}

.menu {
  // position: absolute;
  top: 0;
  left: 0;
  width: 100%;
}

.el-footer {
  background-color: #f2f4f7;
  text-align: center;
  // line-height: 30px !important;
  /* 调整footer高度 */
}

.content {
  position: static;
  display: flex;
  flex-direction: column;
  height: calc(100vh - 160px);
  /* 减去header和footer的高度 */
  background-color: #f2f4f7;
  //overflow-y: auto;
  overflow: auto;
  /* 仅让Main区域可滚动 */
  flex-grow: 1;
  /* 让Main区域占据剩余空间 */
}

@media (max-width: 992px) {
  .content {
    position: static;
    display: flex;
    flex-direction: column;
    height: calc(100vh - 230px);
    /* 减去header和footer的高度 */
    background-color: #f2f4f7;
    //overflow-y: auto;
    overflow: auto;
    /* 仅让Main区域可滚动 */
    flex-grow: 1;
    /* 让Main区域占据剩余空间 */
  }
}

@media (max-width: 1220px) {
  .menu {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    justify-content: flex-start;
  }
}

#canvasEditor {
  display: flex;
  // justify-content: center;
  background: #f2f4f7;
  margin: auto;
}

.el-header {
  position: relative;
}

.canvas-container {
  height: 100%;
  // margin-top: 10px;
}

// 这里开始是style.css文件中的
::-webkit-scrollbar {
  height: 16px;
  width: 16px;
  overflow: visible
}

::-webkit-scrollbar-button {
  width: 0;
  height: 0;
}

::-webkit-scrollbar-corner {
  background: transparent
}

::-webkit-scrollbar-thumb {
  background-color: #ddd;
  background-clip: padding-box;
  border: 4px solid #f2f4f7;
  border-radius: 8px;
  min-height: 24px
}

::-webkit-scrollbar-thumb:hover {
  background-color: #c9c9c9
}

::-webkit-scrollbar-track {
  background: #f2f4f7;
  background-clip: padding-box
}

* {
  margin: 0;
  padding: 0;
}

body {
  background-color: #F2F4F7;
}

ul {
  list-style: none;
}

.menu {
  width: 100%;
  // height: 60px;
  padding: 10px;
  top: 0;
  z-index: 9;
  // position: absolute;
  display: flex;
  align-items: center;
  justify-content: center;
  background: #F2F4F7;
  box-shadow: 0 2px 4px 0 transparent;
}

.menu-divider {
  width: 1px;
  height: 16px;
  margin: 0 8px;
  display: inline-block;
  background-color: #cfd2d8;
}

.menu-item {
  height: 24px;
  display: flex;
  align-items: center;
  position: relative;
}

.menu-item>div {
  width: 24px;
  height: 24px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0 2px;
}

.menu-item>div:hover {
  background: rgba(25, 55, 88, .04);
}

.menu-item>div.active {
  background: rgba(25, 55, 88, .08);
}

.menu-item i {
  width: 16px;
  height: 16px;
  display: inline-block;
  background-repeat: no-repeat;
  background-size: 100% 100%;
}

.menu-item>div>span {
  width: 16px;
  height: 3px;
  display: inline-block;
  border: 1px solid #e2e6ed;
}

.menu-item .select {
  border: none;
  font-size: 12px;
  line-height: 24px;
  user-select: none;
}

.menu-item .select::after {
  position: absolute;
  content: "";
  top: 11px;
  width: 0;
  height: 0;
  right: 2px;
  border-color: #767c85 transparent transparent;
  border-style: solid solid none;
  border-width: 3px 3px 0;
}

.menu-item .options {
  width: 100px;
  position: absolute;
  left: 0;
  top: 25px;
  padding: 10px;
  background: #fff;
  font-size: 14px;
  box-shadow: 0 2px 12px 0 rgb(56 56 56 / 20%);
  border: 1px solid #e2e6ed;
  border-radius: 2px;
  display: none;
}

.menu-item .options.visible {
  display: block;
}

.menu-item .options li {
  padding: 5px;
  margin: 5px 0;
  user-select: none;
  transition: all .3s;
}

.menu-item .options li:hover {
  background-color: #ebecef;
}

.menu-item .options li.active {
  background-color: #e2e6ed;
}

.menu-item .menu-item__font {
  width: 65px;
  position: relative;
}

.menu-item .menu-item__size {
  width: 50px;
  text-align: center;
  position: relative;
}

.menu-item__font .select,
.menu-item__size .select {
  width: 100%;
  height: 100%;
}

.menu-item__undo.no-allow,
.menu-item__redo.no-allow,
.menu-item>div.disable {
  color: #c0c4cc;
  cursor: not-allowed;
  opacity: 0.4;
  pointer-events: none;
}

.menu-item__undo i {
  background-image: url('./assets/images/undo.svg');
}

.menu-item__redo i {
  background-image: url('./assets/images/redo.svg');
}

.menu-item__painter i {
  background-image: url('./assets/images/painter.svg');
}

.menu-item__format i {
  background-image: url('./assets/images/format.svg');
}

.menu-item__size-add i {
  background-image: url('./assets/images/size-add.svg');
}

.menu-item__size-minus i {
  background-image: url('./assets/images/size-minus.svg');
}

.menu-item__bold i {
  background-image: url('./assets/images/bold.svg');
}

.menu-item__italic i {
  background-image: url('./assets/images/italic.svg');
}

.menu-item .menu-item__underline {
  width: 30px;
  position: relative;
}

.menu-item__underline>i {
  flex-shrink: 0;
  background-image: url('./assets/images/underline.svg');
}

.menu-item__underline .select {
  width: 100%;
  height: 100%;
}

.menu-item .menu-item__underline .options {
  width: 128px;
}

.menu-item .menu-item__underline li {
  padding: 1px 5px;
}

.menu-item__underline li i {
  pointer-events: none;
}

.menu-item__underline li[data-decoration-style="solid"] {
  background-image: url('./assets/images/line-single.svg');
}

.menu-item__underline li[data-decoration-style="double"] {
  background-image: url('./assets/images/line-double.svg')
}

.menu-item__underline li[data-decoration-style="dashed"] {
  background-image: url('./assets/images/line-dash-small-gap.svg');
}

.menu-item__underline li[data-decoration-style="dotted"] {
  background-image: url('./assets/images/line-dot.svg');
}

.menu-item__underline li[data-decoration-style="wavy"] {
  background-image: url('./assets/images/line-wavy.svg');
}

.menu-item__strikeout i {
  background-image: url('./assets/images/strikeout.svg');
}

.menu-item__superscript i {
  background-image: url('./assets/images/superscript.svg');
}

.menu-item__subscript i {
  background-image: url('./assets/images/subscript.svg');
}

.menu-item__color,
.menu-item__highlight {
  display: flex;
  flex-direction: column;
}

.menu-item__color #color,
.menu-item__highlight #highlight {
  width: 1px;
  height: 1px;
  visibility: hidden;
  outline: none;
  appearance: none;
}

.menu-item__color i {
  background-image: url('./assets/images/color.svg');
}

.menu-item__color span {
  background-color: #000000;
}

.menu-item__highlight i {
  background-image: url('./assets/images/highlight.svg');
}

.menu-item__highlight span {
  background-color: #ffff00;
}

.menu-item .menu-item__title {
  width: 60px;
  position: relative;
}

.menu-item__title .select {
  width: calc(100% - 20px);
  height: 100%;
}

.menu-item__title i {
  transform: translateX(-5px);
  background-image: url('./assets/images/title.svg');
}

.menu-item__title .options {
  width: 120px;
}

.menu-item__left i {
  background-image: url('./assets/images/left.svg');
}

.menu-item__center i {
  background-image: url('./assets/images/center.svg');
}

.menu-item__right i {
  background-image: url('./assets/images/right.svg');
}

.menu-item__alignment i {
  background-image: url('./assets/images/alignment.svg');
}

.menu-item__justify i {
  background-image: url('./assets/images/justify.svg');
}

.menu-item__row-margin {
  position: relative;
}

.menu-item__row-margin i {
  background-image: url('./assets/images/row-margin.svg');
}

.menu-item__list {
  position: relative;
}

.menu-item__list i {
  background-image: url('./assets/images/list.svg');
}

.menu-item__list .options {
  width: 130px;
}

.menu-item__list .options>ul>li * {
  pointer-events: none;
}

.menu-item__list .options>ul>li li {
  margin-left: 18px;
}

.menu-item__list .options>ul>li[data-list-style='checkbox'] li::marker {
  font-size: 11px;
}

.menu-item__image i {
  background-image: url('./assets/images/image.svg');
}

.menu-item__image input {
  display: none;
}

.menu-item__table {
  position: relative;
}

.menu-item__table i {
  background-image: url('./assets/images/table.svg');
}

.menu-item .menu-item__table__collapse {
  width: 270px;
  height: 310px;
  background: #fff;
  box-shadow: 0 2px 12px 0 rgb(56 56 56 / 20%);
  border: 1px solid #e2e6ed;
  box-sizing: border-box;
  border-radius: 2px;
  position: absolute;
  display: none;
  z-index: 99;
  top: 25px;
  left: 0;
  transform: translateX(-50%);
  padding: 14px 27px;
  cursor: auto;
}

.menu-item .menu-item__table__collapse .table-close {
  position: absolute;
  right: 10px;
  top: 5px;
  cursor: pointer;
}

.menu-item .menu-item__table__collapse .table-close:hover {
  color: #7d7e80;
}

.menu-item .menu-item__table__collapse:hover {
  background: #fff;
}

.menu-item .menu-item__table__collapse .table-title {
  display: flex;
  justify-content: flex-start;
  padding-bottom: 5px;
  border-bottom: 1px solid #e2e6ed;
}

.table-title span {
  font-size: 12px;
  color: #3d4757;
  display: inline;
  margin: 0;
}

.table-panel {
  cursor: pointer;
}

.table-panel::v-deep .table-row {
  display: flex;
  flex-wrap: nowrap;
  margin-top: 10px;
  pointer-events: none;
}

.table-panel::v-deep .table-cel{
  width: 16px;
  height: 16px;
  box-sizing: border-box;
  border: 1px solid #e2e6ed;
  position: relative;
  margin-right: 6px;
  pointer-events: none;
}

.table-panel::v-deep .table-cel.active {
  border: 1px solid rgba(73, 145, 242, .2);
  background: rgba(73, 145, 242, .15);
}

.table-panel::v-deep .table-row .table-cel:last-child {
  margin-right: 0;
}

.menu-item__hyperlink i {
  background-image: url('./assets/images/hyperlink.svg');
}

.menu-item__separator {
  position: relative;
}

.menu-item__separator>i {
  background-image: url('./assets/images/separator.svg');
}

.menu-item .menu-item__separator .options {
  width: 128px;
}

.menu-item .menu-item__separator li {
  padding: 1px 5px;
}

.menu-item__separator li i {
  pointer-events: none;
}

.menu-item__separator li[data-separator="0,0"] {
  background-image: url('./assets/images/line-single.svg');
}

.menu-item__separator li[data-separator="1,1"] {
  background-image: url('./assets/images/line-dot.svg');
}

.menu-item__separator li[data-separator="3,1"] {
  background-image: url('./assets/images/line-dash-small-gap.svg');
}

.menu-item__separator li[data-separator="4,4"] {
  background-image: url('./assets/images/line-dash-large-gap.svg');
}

.menu-item__separator li[data-separator="7,3,3,3"] {
  background-image: url('./assets/images/line-dash-dot.svg');
}

.menu-item__separator li[data-separator="6,2,2,2,2,2"] {
  background-image: url('./assets/images/line-dash-dot-dot.svg');
}

.menu-item__watermark>i {
  background-image: url('./assets/images/watermark.svg');
}

.menu-item__watermark {
  position: relative;
}

.menu-item__codeblock i {
  background-image: url('./assets/images/codeblock.svg');
}

.menu-item__page-break i {
  background-image: url('./assets/images/page-break.svg');
}

.menu-item__control {
  position: relative;
}

.menu-item__control i {
  background-image: url('./assets/images/control.svg');
}

.menu-item__checkbox i {
  background-image: url('./assets/images/checkbox.svg');
}

.menu-item__radio i {
  background-image: url('./assets/images/radio.svg');
}

.menu-item__latex i {
  background-image: url('./assets/images/latex.svg');
}

.menu-item__date {
  position: relative;
}

.menu-item__date i {
  background-image: url('./assets/images/date.svg');
}

.menu-item__date .options {
  width: 160px;
}

.menu-item__block i {
  background-image: url('./assets/images/block.svg');
}

.menu-item .menu-item__control .options {
  width: 55px;
}

.menu-item__search {
  position: relative;
}

.menu-item__search i {
  background-image: url('./assets/images/search.svg');
}

.menu-item .menu-item__search__collapse {
  width: 260px;
  height: 72px;
  box-sizing: border-box;
  position: absolute;
  display: none;
  z-index: 99;
  top: 25px;
  left: 0;
  background: #ffffff;
  box-shadow: 0px 5px 5px #e3dfdf;
}

.menu-item .menu-item__search__collapse:hover {
  background: #ffffff;
}

.menu-item .menu-item__search__collapse>div {
  width: 250px;
  height: 36px;
  padding: 0 5px;
  line-height: 36px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  border-radius: 4px;
}

.menu-item .menu-item__search__collapse>div input {
  width: 205px;
  height: 27px;
  appearance: none;
  background-color: #fff;
  background-image: none;
  border-radius: 4px;
  border: 1px solid #ebebeb;
  box-sizing: border-box;
  color: #606266;
  display: inline-block;
  line-height: 27px;
  outline: none;
  padding: 0 5px;
}

.menu-item .menu-item__search__collapse>div span {
  height: 100%;
  color: #dcdfe6;
  font-size: 25px;
  display: inline-block;
  border: 0;
  padding: 0 10px;
}

.menu-item .menu-item__search__collapse__replace button {
  display: inline-block;
  border: 1px solid #e2e6ed;
  border-radius: 2px;
  background: #fff;
  line-height: 22px;
  padding: 0 6px;
  white-space: nowrap;
  margin-left: 4px;
  cursor: pointer;
  font-size: 12px;
}

.menu-item .menu-item__search__collapse__replace button:hover {
  background: rgba(25, 55, 88, .04);
}

.menu-item .menu-item__search__collapse__search {
  position: relative;
}

.menu-item .menu-item__search__collapse__search label {
  right: 110px;
  font-size: 12px;
  color: #3d4757;
  position: absolute;
}

.menu-item .menu-item__search__collapse__search>input {
  padding: 5px 90px 5px 5px !important;
}

.menu-item .menu-item__search__collapse__search>div {
  width: 28px;
  height: 27px;
  display: flex;
  justify-content: center;
  align-items: center;
  position: absolute;
  border-left: 1px solid #e2e6ed;
  transition: all .5s;
}

.menu-item .menu-item__search__collapse__search>div:hover {
  background-color: rgba(25, 55, 88, .04);
}

.menu-item .menu-item__search__collapse__search i {
  width: 6px;
  height: 8px;
  transform: translateY(1px);
}

.menu-item .menu-item__search__collapse__search .arrow-left {
  right: 76px;
}

.menu-item .menu-item__search__collapse__search .arrow-left i {
  background: url(./assets/images/arrow-left.svg) no-repeat;
}

.menu-item .menu-item__search__collapse__search .arrow-right {
  right: 48px;
}

.menu-item .menu-item__search__collapse__search .arrow-right i {
  background: url(./assets/images/arrow-right.svg) no-repeat;
}

.menu-item__print i {
  background-image: url('./assets/images/print.svg');
}

.catalog {
  width: 250px;
  position: absolute;
  left: 0;
  bottom: 0;
  top: 100px;
  padding: 0 20px 40px 20px;
}

.catalog .catalog__header {
  height: 48px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  border-bottom: 1px solid #e2e6ed;
}

.catalog .catalog__header span {
  color: #3d4757;
  font-size: 14px;
  font-weight: bold;
}

.catalog .catalog__header i {
  width: 16px;
  height: 16px;
  cursor: pointer;
  display: inline-block;
  background: url(./assets/images/close.svg) no-repeat;
  transition: all .2s;
}

.catalog .catalog__header>div:hover {
  background: rgba(235, 238, 241);
}

.catalog__main {
  height: calc(100% - 60px);
  padding: 10px 0;
  overflow-y: auto;
  overflow-x: hidden;
}

.catalog__main .catalog-item {
  width: 100%;
  padding-left: 10px;
  box-sizing: border-box;
}

.catalog__main>.catalog-item {
  padding-left: 0;
}

.catalog__main .catalog-item .catalog-item__content {
  width: 100%;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.catalog__main .catalog-item .catalog-item__content:hover>span {
  color: #4991f2;
}

.catalog__main .catalog-item .catalog-item__content span {
  color: #3d4757;
  line-height: 30px;
  font-size: 12px;
  white-space: nowrap;
  cursor: pointer;
  user-select: none;
}

.editor>div {
  margin: 0 auto;
  /* margin: 80px auto; */
}

.ce-page-container canvas {
  box-shadow: rgb(158 161 165 / 40%) 0px 2px 12px 0px;
}

.comment {
  width: 250px;
  height: 650px;
  position: absolute;
  transform: translateX(420px);
  top: 200px;
  left: 50%;
  overflow-y: auto;
}

.comment-item {
  background: #ffffff;
  border: 1px solid #e2e6ed;
  position: relative;
  border-radius: 8px;
  padding: 15px;
  font-size: 14px;
  margin-bottom: 20px;
  cursor: pointer;
  transition: all .5s;
}

.comment-item:hover {
  border-color: #c0c6cf;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, .1);
}

.comment-item.active {
  border-color: #E99D00;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, .1);
}

.comment-item__title {
  height: 22px;
  position: relative;
  display: flex;
  align-items: center;
  color: #c1c6ce;
}

.comment-item__title span:first-child {
  background-color: #dbdbdb;
  width: 4px;
  height: 16px;
  margin-right: 5px;
  display: inline-block;
  border-radius: 999px;
}

.comment-item__title span:nth-child(2) {
  width: 200px;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.comment-item__title i {
  width: 16px;
  height: 16px;
  cursor: pointer;
  position: absolute;
  right: -8px;
  top: -8px;
  background: url(./assets/images/close.svg) no-repeat;
}

.comment-item__title i:hover {
  opacity: 0.6;
}

.comment-item__info {
  height: 28px;
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.comment-item__info>span:first-child {
  font-weight: 600;
}

.comment-item__info>span:last-child {
  color: #c1c6ce;
}

.comment-item__content {
  line-height: 22px;
}

.footer {
  width: 100%;
  min-height: 30px;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  justify-content: space-between;
  background: #f2f4f7;
  z-index: 9;
  position: absolute;
  bottom: 0;
  left: 0;
  font-size: 12px;
  padding: 0 4px 0 20px;
  box-sizing: border-box;
}

.footer>div:first-child {
  display: flex;
  align-items: center;
}

.footer .catalog-mode {
  padding: 1px;
  position: relative;
}

.footer .catalog-mode i {
  width: 16px;
  height: 16px;
  margin-right: 5px;
  cursor: pointer;
  display: inline-block;
  background-image: url('./assets/images/catalog.svg');
}

.footer .page-mode {
  padding: 1px;
  position: relative;
}

.footer .page-mode i {
  width: 16px;
  height: 16px;
  margin-right: 5px;
  cursor: pointer;
  display: inline-block;
  background-image: url('./assets/images/page-mode.svg');
}

.footer .options {
  width: 100px;
  position: absolute;
  left: 0;
  bottom: 25px;
  padding: 10px;
  background: #fff;
  font-size: 14px;
  box-shadow: 0 2px 12px 0 rgb(56 56 56 / 20%);
  border: 1px solid #e2e6ed;
  border-radius: 2px;
  display: none;
}

.footer .options.visible {
  display: block;
}

.footer .options li {
  padding: 5px;
  margin: 5px 0;
  user-select: none;
  transition: all .3s;
  text-align: center;
  cursor: pointer;
}

.footer .options li:hover {
  background-color: #ebecef;
}

.footer .options li.active {
  background-color: #e2e6ed;
}

.footer>div:first-child>span {
  display: inline-block;
  margin-right: 5px;
  letter-spacing: 1px;
}

.footer>div:last-child {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.footer>div:last-child>div {
  width: 24px;
  height: 24px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.footer>div:last-child>div:hover {
  background: rgba(25, 55, 88, .04);
}

.footer>div:last-child i {
  width: 16px;
  height: 16px;
  display: inline-block;
  cursor: pointer;
}

.footer .editor-option i {
  background-image: url('./assets/images/option.svg');
}

.footer .page-scale-minus i {
  background-image: url('./assets/images/page-scale-minus.svg');
}

.footer .page-scale-add i {
  background-image: url('./assets/images/page-scale-add.svg');
}

.footer .page-scale-percentage {
  cursor: pointer;
  user-select: none;
}

.footer .fullscreen i {
  background-image: url('./assets/images/request-fullscreen.svg');
}

.footer .fullscreen.exist i {
  background-image: url('./assets/images/exit-fullscreen.svg');
}

.footer .paper-margin i {
  background-image: url('./assets/images/paper-margin.svg');
}

.footer .editor-mode {
  cursor: pointer;
  user-select: none;
}

.footer .paper-size {
  position: relative;
}

.footer .paper-size i {
  background-image: url('./assets/images/paper-size.svg');
}

.footer .paper-size .options {
  right: 0;
  left: unset;
}

.footer .paper-direction {
  position: relative;
}

.footer .paper-direction i {
  background-image: url('./assets/images/paper-direction.svg');
}

.footer .paper-direction .options {
  right: 0;
  left: unset;
}

.ce-contextmenu-signature {
  background-image: url('./assets/images/signature.svg');
}

.ce-contextmenu-word-tool {
  background-image: url('./assets/images/word-tool.svg');
}

</style>
